/**
 * @author Tin Pham / 7inpham@gmail.com
 */
var TinP = (function () {
    'use strict';
    var clock = new THREE.Clock();
    var scene;
    var renderer;
    var camera;
    var robot;
    var car;
    var orbitControls;
    var stage = "playing";
    var container;

    var load = function () {
        var loader = new THREE.JSONLoader();
        loader.load('models/car/car.js', function (geometry, materials) {
            var material = new THREE.MeshLambertMaterial({
                map : THREE.ImageUtils.loadTexture('models/car/gtare.jpg'),
                colorAmbient : [0.480000026226044, 0.480000026226044, 0.480000026226044],
                colorDiffuse : [0.480000026226044, 0.480000026226044, 0.480000026226044],
                colorSpecular : [0.8999999761581421, 0.8999999761581421, 0.8999999761581421]
            });
            car = new THREE.Mesh(geometry, material);
            car.receiveShadow = true;
            car.castShadow = true;
            //this.car.rotation.y = -Math.PI / 5;
            car.scale.x = car.scale.y = car.scale.z = 0.5;
            car.position.x = 50;
            scene.add(car);

            loader.load('models/blade/blade.js', function (geometry, materials) {
                var rotationY = new THREE.Matrix4().makeRotationY(Math.PI / 2);
                geometry.applyMatrix(rotationY);
                geometry.computeMorphNormals();
                /*
				var material = new THREE.MeshLambertMaterial({
				//map : THREE.ImageUtils.loadTexture('models/blade/blade.jpg'),
				colorAmbient : [0.480000026226044, 0.480000026226044, 0.480000026226044],
				colorDiffuse : [0.480000026226044, 0.480000026226044, 0.480000026226044],
				colorSpecular : [0.8999999761581421, 0.8999999761581421, 0.8999999761581421]
				});
				 */

                var material = new THREE.MeshPhongMaterial({
                    map : THREE.ImageUtils.loadTexture('models/blade/blade.jpg'),
                    color : 0xffffff,
                    specular : 0xffffff,
                    shininess : 20,
                    morphTargets : true,
                    //morphNormals : true,
                    vertexColors : THREE.FaceColors,
                    shading : THREE.SmoothShading
                });
                /*
				var material = new THREE.MeshPhongMaterial({
				map: THREE.ImageUtils.loadTexture('models/blade/blade.jpg'),
				ambient: 0x999999,
				color: 0xffffff,
				specular: 0xffffff,
				shininess: 25,
				morphTargets: true
				});
				 */
                robot = new THREE.MorphAnimMesh(geometry, material);
                //robot.duration = 5000;
                // random animation offset
                //robot.time = 1000 * Math.random();
                robot.parseAnimations(); // << Funkton fuer Faule P.O.'s :-P
                robot.playAnimation('stand', 4);

                robot.receiveShadow = true;
                robot.castShadow = true;
                //robot.rotation.y = Math.PI / 5;
                robot.scale.x = robot.scale.y = robot.scale.z = 1;
                //robot.position.x = -50;
                robot.position.y = 20;
                //robot.add(camera);

                scene.add(robot);
            });
        });
    };

    var addControls = function () {
        var timer;
        var moveState = {
            moving : false,
            front : false,
            Backwards : false,
            left : false,
            right : false,
            speed : 5,
            angle : 0
        };
        var move = function () {
            var speed = moveState.speed;
            var direction = moveState.angle;
            if (moveState.front && !moveState.left && !moveState.Backwards && !moveState.right) {
                direction += 0;
            }
            if (moveState.front && moveState.left && !moveState.Backwards && !moveState.right) {
                direction += 45;
            }
            if (!moveState.front && moveState.left && !moveState.Backwards && !moveState.right) {
                direction += 90;
            }
            if (!moveState.front && moveState.left && moveState.Backwards && !moveState.right) {
                direction += 135;
            }
            if (!moveState.front && !moveState.left && moveState.Backwards && !moveState.right) {
                direction += 180;
            }
            if (!moveState.front && !moveState.left && moveState.Backwards && moveState.right) {
                direction += 225;
            }
            if (!moveState.front && !moveState.left && !moveState.Backwards && moveState.right) {
                direction += 270;
            }
            if (moveState.front && !moveState.left && !moveState.Backwards && moveState.right) {
                direction += 315;
            }

            robot.rotation.y = direction * Math.PI / 180;
            robot.position.x -= Math.sin(direction * Math.PI / 180) * speed;
            robot.position.z -= Math.cos(direction * Math.PI / 180) * speed;
        };
        document.addEventListener('keydown', function (e) {
            if (!/65|68|83|87/.test(e.keyCode)) {
                return;
            }
            if (e.keyCode === 87) {
                moveState.front = true;
                moveState.Backwards = false;
            } else if (e.keyCode === 83) {
                moveState.Backwards = true;
                moveState.front = false;
            } else if (e.keyCode === 65) {
                moveState.left = true;
                moveState.right = false;
            } else if (e.keyCode === 68) {
                moveState.right = true;
                moveState.left = false;
            }
            if (!moveState.moving) {
                moveState.moving = true;
                move();
                robot.playAnimation('run', 7);
                timer = setInterval(function () {
                    move();
                }, 1000 / 60);
            }
        }, false);
        document.addEventListener('keyup', function (e) {
            if (!/65|68|83|87/.test(e.keyCode)) {
                return;
            }
            if (e.keyCode === 87) {
                moveState.front = false;
            } else if (e.keyCode === 83) {
                moveState.Backwards = false;
            } else if (e.keyCode === 65) {
                moveState.left = false;
            } else if (e.keyCode === 68) {
                moveState.right = false;
            }
            if (!moveState.front && !moveState.Backwards && !moveState.left && !moveState.right) {
                moveState.moving = false;
                robot.playAnimation('stand', 3);
                clearInterval(timer);
            }
        }, false);
    };

    var initScene = function (container) {
        var WIDTH = window.innerWidth;
        var HEIGHT = window.innerHeight;
        var VIEW_ANGLE = 45;
        var ASPECT = WIDTH / HEIGHT;
        var NEAR = 1;
        var FAR = 2000;

        scene = new THREE.Scene();
        scene.fog = new THREE.Fog(0xffffff, 1000, 4000);

        renderer = new THREE.WebGLRenderer({
            antialias : true
        });
        renderer.setSize(WIDTH, HEIGHT);
        renderer.setClearColor(scene.fog.color, 1);
        renderer.gammaInput = true;
        renderer.gammaOutput = true;
        renderer.shadowMapEnabled = true;
        renderer.shadowMapSoft = true;
        renderer.shadowMapCascade = true;
        renderer.shadowMapType = THREE.PCFSoftShadowMap;
        renderer.shadowMapAutoUpdate = true;

        container.appendChild(renderer.domElement);

        camera = new THREE.PerspectiveCamera(VIEW_ANGLE, ASPECT, NEAR, FAR);
        camera.position.set(0, 450, 0);
        scene.add(camera);

        orbitControls = new THREE.OrbitControls(camera, renderer.domElement);
        /*
		// LIGHTS
		var directionalLight = new THREE.DirectionalLight( 0xffffff, 1.475 );
		directionalLight.position.set( 100, 100, -100 );
		scene.add( directionalLight );
		var hemiLight = new THREE.HemisphereLight( 0xffffff, 0xffffff, 1.25 );
		hemiLight.color.setHSL( 0.6, 1, 0.75 );
		hemiLight.groundColor.setHSL( 0.1, 0.8, 0.7 );
		hemiLight.position.y = 500;
		scene.add( hemiLight );
		// SKYDOME
		var vertexShader = document.getElementById( 'vertexShader' ).textContent;
		var fragmentShader = document.getElementById( 'fragmentShader' ).textContent;
		var uniforms = {
		topColor: 	 { type: "c", value: new THREE.Color( 0x0077ff ) },
		bottomColor: { type: "c", value: new THREE.Color( 0xffffff ) },
		offset:		 { type: "f", value: 400 },
		exponent:	 { type: "f", value: 0.6 }
		}
		uniforms.topColor.value.copy( hemiLight.color );

		scene.fog.color.copy( uniforms.bottomColor.value );

		var skyGeo = new THREE.SphereGeometry( 4000, 32, 15 );
		var skyMat = new THREE.ShaderMaterial( { vertexShader: vertexShader, fragmentShader: fragmentShader, uniforms: uniforms, side: THREE.BackSide } );

		var sky = new THREE.Mesh( skyGeo, skyMat );
		scene.add( sky );
		 */
        // LIGHTS
        scene.add(new THREE.AmbientLight(0x222222));

        var light = new THREE.DirectionalLight(0xffffff, 2.25);
        light.position.set(200, 450, 500);
        light.castShadow = true;
        light.shadowMapWidth = 1024;
        light.shadowMapHeight = 1024;
        light.shadowMapDarkness = 0.95;
        //light.shadowCameraVisible = true;
        light.shadowCascade = true;
        light.shadowCascadeCount = 3;
        light.shadowCascadeNearZ = [-1.000, 0.995, 0.998];
        light.shadowCascadeFarZ = [0.995, 0.998, 1.000];
        light.shadowCascadeWidth = [1024, 1024, 1024];
        light.shadowCascadeHeight = [1024, 1024, 1024];
        scene.add(light);

        //  GROUND
        var gt = THREE.ImageUtils.loadTexture("textures/grasslight-big.jpg");
        var gg = new THREE.PlaneGeometry(16000, 16000);
        var gm = new THREE.MeshPhongMaterial({
            color : 0xffffff,
            map : gt
        });
        var ground = new THREE.Mesh(gg, gm);
        ground.rotation.x =  -Math.PI / 2;
        ground.material.map.repeat.set(64, 64);
        ground.material.map.wrapS = ground.material.map.wrapT = THREE.RepeatWrapping;
        ground.receiveShadow = true;
        scene.add(ground);

        load();
        window.addEventListener('resize', function () {
            camera.aspect = window.innerWidth / window.innerHeight;
            camera.updateProjectionMatrix();
            renderer.setSize(window.innerWidth, window.innerHeight);
        }, false);
        addControls();
    };

    var animate = function () {
        requestAnimationFrame(animate);
        if (stage === "playing") {
            // camera rotate x
            //camera.position.x = robot.position.x;
            //camera.position.z = robot.position.z;

            //camera rotate y
            //camera.position.x = robot.position.x + robot.camera.distance * Math.cos( (robot.camera.y) * Math.PI / 360 );
            //camera.position.y = robot.position.y;
            //camera.position.z = robot.position.z + robot.camera.distance * Math.cos( (robot.camera.y) * Math.PI / 360 );

            //	camera.position.y += 1;
            //console.log(camera.position.z)
            //camera.rotation.x = -Math.PI / 12;
            var delta = clock.getDelta();
            if (car) {
                car.rotation.y += delta;
            }
            if (robot) {
                //camera.position.set(robot.position.x, 450, robot.position.z);
                //var vec3 = new THREE.Vector3(robot.position.x, robot.position.y, robot.position.z);
                //camera.lookAt(robot.position);
                //camera.position.x = robot.position.x;
                //camera.position.z = robot.position.z;
                //camera.position.y = robot.position.y;
                orbitControls.update();
                robot.updateAnimation(1000 * delta);
            }
            renderer.render(scene, camera);
        } else {
            container.innerHTML = "Game Over";
        }
    };

    var TinP = function (container) {
        console.log("TinP 0.1");
        var char1 = new TinP.ExCharacter();
        char1.update();
        char1.move();
        char1.override("Anc ");
        container.innerHTML = "";
        initScene(container);
        animate();
    };

    return TinP;
})();

TinP.Character = (function () {
    'use strict';
    var _text = " Private";
    var Character = function () {
        this.text = "Character";
        console.log(this.text + _text);
    };
    Character.prototype.constructor = Character;
    Character.prototype.update = function () {
        console.log("Updated " + this.text + _text);
    };
    Character.prototype.override = function (value) {
        console.log(_text + value);
    };
    return Character;
}());

TinP.ExCharacter = (function () {
    'use strict';
    var ExCharacter = function () {
        TinP.Character.call(this);
    };
    ExCharacter.prototype = Object.create(TinP.Character.prototype);
    ExCharacter.prototype.constructor = ExCharacter;
    ExCharacter.prototype.move = function () {
        console.log("Move");
    };
    ExCharacter.prototype.override = function (value) {
        TinP.Character.prototype.override.call(this, value);
        console.log("Ovr");
    };
    return ExCharacter;
}());
